﻿using CommonlyUtils;
using ImClientApi.Utils;
using ImModels.Service.Models.Data;
using ImModels.View;
using ImModels.View.MsgJson;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.VisualBasic;
using System.Linq;
using System.Security.Cryptography;
using xl.webapi.db_helper_interface;

namespace ImClientApi.Controllers
{

    /// <summary>
    /// 群组 控制器
    /// </summary>
    public class GroupController : BaseAuthController
    {
        /// <summary>
        /// 创建一个群聊 创建之后应该返回一个会话
        /// 1.创建群
        /// 2.给发起者加一个会话
        /// 3.给所有在线的用户 加一个会话
        /// 4.给所有在线的用户发送 ws 消息，对方可以显示新会话 可以选择进入会话之类的
        /// </summary>
        /// <param name="reqview"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResView<MySession>> Create([FromBody] ReqView<CreateGroupReq> reqview)
        {
            var jwtUser = GetUseByJwtToken();

            if (jwtUser.BizUserID != reqview.Data.BizUserId || jwtUser.EnterpriseId != reqview.AppId.ToString())
            {
                return await ReturnFailed(302, "当前Token和登录用户信息不匹配，请核对修改后重试");
            }

            var reqData = reqview.Data;
            //企业ID
            var enterId = reqview.AppId;
            //群组ID
            var groupId = Builder.GetNewSnowId();

            var fullName = reqData.FullName;
            if (fullName.IsNull())
            {
                fullName = string.Join(",", reqData.ToUser.Select(p => p.FullName));
                if (fullName.Length > 110)
                {
                    fullName = fullName.Substring(0, 100) + "...";
                }
            }
            var headImg = reqData.HeadImg;
            if (string.IsNullOrWhiteSpace(headImg))
            {

                headImg = string.Join(",", reqData.ToUser.Take(9).Select(p => p.HeadImg));
            }
            if (string.IsNullOrWhiteSpace(headImg))
            {
                headImg = ConfigUtils.GetConfigToString("GroupDefaultImage");
            }

            var BizUserDbItem = await DbUtils.DbHelper.GetOneAsync<Users>(p => p.EnterpriseId == enterId && p.BizUserId == jwtUser.BizUserID);
            if (BizUserDbItem == null || BizUserDbItem.KID == 0)
            {
                return new ResView<MySession>() { code = 500, msg = "当前用户不存在，请核对后重试" };
            }

            reqData.ToUser = reqData.ToUser.Where(p => p.BizUserId != jwtUser.BizUserID).ToList();

            #region 1 添加一个群组
            var addDb = await DbUtils.DbHelper.AddItemAsync<ImGroups>(new ImGroups()
            {
                KID = groupId,
                States = 0,
                CreateTime = DateTime.Now,
                EnterpriseId = reqview.AppId,
                CreateUserId = reqData.BizUserId,
                FullName = fullName,
                Comment = reqData.Comment,
                UserCnt = reqData.ToUser.Count(),
                HeadImg = headImg,
                ExJson = reqData.ToJson(),
                Flags = reqData.Flags,
                IsDeleted = 0
            });
            if (addDb == 0)
            {
                return new ResView<MySession>() { code = 500, msg = "群聊创建失败，请修改后重试" };
            }
            #endregion

            #region 2 添加群-用户关联表数据 和 Users表数据
            var groupUserItems = new List<ImGroupUser>();
            groupUserItems.Add(new ImGroupUser()
            {
                KID = Builder.GetNewSnowId(),
                EnterpriseId = reqview.AppId,
                GroupId = groupId,
                BizUserId = reqData.BizUserId,
                JoinTime = DateTime.Now,
                JoinState = 1,
                JoinComment = "",
                InviterBizUserId = reqData.BizUserId,
                EnableTime = DateTime.Now.AddSeconds(-1)
            });
            foreach (var toUser in reqData.ToUser)
            {
                if (toUser.BizUserId == jwtUser.BizUserID)
                {
                    continue;
                }
                groupUserItems.Add(new ImGroupUser()
                {
                    KID = Builder.GetNewSnowId(),
                    EnterpriseId = reqview.AppId,
                    GroupId = groupId,
                    BizUserId = toUser.BizUserId,
                    JoinTime = DateTime.Now,
                    JoinState = 1,
                    JoinComment = "",
                    InviterBizUserId = reqData.BizUserId,
                    EnableTime = DateTime.Now.AddSeconds(-1)
                });
            }
            if (groupUserItems.Count() > 0)
                addDb = await DbUtils.DbHelper.AddItemsAsync<ImGroupUser>(groupUserItems);
            if (addDb == 0)
            {
                await DbUtils.DbHelper.DeleteItemAsync<ImGroups>(p => p.KID == groupId);
                return new ResView<MySession>() { code = 500, msg = "群聊用户创建失败，请稍后重试" };
            }

            var toUserIds = reqData.ToUser.Select(p => p.BizUserId).ToList();
            var existUser = await DbUtils.DbHelper.GetListAsync<Users>(p => toUserIds.Contains(p.BizUserId) && p.EnterpriseId == reqview.AppId);
            var needAddUsers = new List<Users>();
            foreach (var item in reqData.ToUser)
            {
                if (existUser.Count(p => p.BizUserId == item.BizUserId) == 0)
                {
                    needAddUsers.Add(new Users()
                    {
                        KID = Builder.GetNewSnowId(),
                        States = 0,
                        IsDeleted = 0,
                        CreateTime = DateTime.Now,
                        LoginTime = "",
                        EnterpriseId = enterId,
                        JobName = item.JobName,
                        BizUserId = item.BizUserId,
                        ContactTel = "",
                        FullName = item.FullName,
                        HeadImg = item.HeadImg,
                        UserInfo = ""
                    });
                }
            }
            if (needAddUsers.Count() > 0)
                addDb = await DbUtils.DbHelper.AddItemsAsync<Users>(needAddUsers);
            #endregion

            #region 3 加一个会话  给 自己和 所有用户 都加上这个会话
            var sessionKid = Builder.GetNewSnowId();
            var sessionItems = new List<MySession>();
            sessionItems.Add(new MySession()
            {
                SessionId = sessionKid,
                EnterpriseId = reqview.AppId,
                BizUserId = reqData.BizUserId,
                ToUserId = groupId.ToString(),
                IsGroup = 1,
                FullName = fullName,
                HeadImg = headImg,
                CreateTime = DateTime.Now,
            });
            foreach (var toUser in reqData.ToUser)
            {
                sessionItems.Add(new MySession()
                {
                    SessionId = sessionKid,
                    EnterpriseId = reqview.AppId,
                    BizUserId = toUser.BizUserId,
                    ToUserId = groupId.ToString(),
                    IsGroup = 1,
                    FullName = fullName,
                    HeadImg = headImg
                });
            }

            addDb = await DbUtils.DbHelper.AddItemsAsync<MySession>(sessionItems);
            if (addDb == 0)
            {
                await DbUtils.DbHelper.DeleteItemAsync<ImGroups>(p => p.KID == groupId);
                await DbUtils.DbHelper.DeleteItemAsync<ImGroupUser>(p => p.GroupId == groupId);
                return new ResView<MySession>() { code = 500, msg = "群聊会话创建失败，请稍后重试" };
            }
            var selfSessionDb = await DbUtils.DbHelper.GetOneAsync<MySession>(p => p.SessionId == sessionKid && p.BizUserId == reqData.BizUserId);
            #endregion

            #region 4 判断 目标用户 给所有的用户 发送ws消息
            var sessionmsg = new Msg_Session
            {
                type = 1,
                sessionid = sessionKid,
                session = new SessionItem()
                {
                    isgroup = 1,
                    toUserId = groupId.ToString(),
                    fullname = fullName,
                    headimg = headImg,
                    flags = reqData.Flags
                }
            };
            //var toUserIds = reqData.ToUser.Select(p => p.BizUserId).ToList();
            toUserIds.Add(reqData.BizUserId);
            await ImMsgLogic.SendSessionMsg(sessionmsg, toUserIds, BizUserDbItem.KID);
            #endregion

            return new ResView<MySession>() { code = 200, msg = "ok", data = selfSessionDb };
        }

        /// <summary>
        /// 删除一个群 删除 接口 返回200 前端就可以移除此会话了
        /// data参数为 唯一的会话ID
        /// </summary>
        /// <param name="reqview"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResView> Del([FromBody] ReqView<long> reqview)
        {
            var jwtUser = GetUseByJwtToken();

            if (jwtUser.EnterpriseId != reqview.AppId.ToString())
            {
                return await ReturnFailed(302, "当前Token和登录用户信息不匹配，请核对修改后重试");
            }

            if (reqview.Data <= 0)
            {
                return await ReturnFailed(500, "被删除的会话ID不能为空,请修改后重试");
            }

            var delDb = await DbUtils.DbHelper.DeleteItemAsync<MySession>(p => p.SessionId == reqview.Data && p.BizUserId == jwtUser.BizUserID);

            return new ResView()
            {
                code = delDb > 0 ? 200 : 500,
                msg = delDb > 0 ? "删除成功" : "删除失败"
            };
        }

        /// <summary>
        /// 邀请用户 加入一个 已存在 的群聊
        /// 1.先写 写关联表，再修改群人数相关，
        /// 2.给新加的用户发消息 type = 1的建群消息
        /// 3.给已有用户发送 type = 2的普通聊天消息
        /// </summary>
        /// <param name="reqview"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResView> AddUsers([FromBody] ReqView<JoinGroupReq> reqview)
        {
            var jwtUser = GetUseByJwtToken();

            if (jwtUser.BizUserID != reqview.Data.BizUserId || jwtUser.EnterpriseId != reqview.AppId.ToString())
            {
                return await ReturnFailed(302, "当前Token和登录用户信息不匹配，请核对修改后重试");
            }

            var reqData = reqview.Data;
            //企业ID
            var enterId = reqview.AppId;
            //群组ID
            var groupId = reqData.GroupId;

            var sessionKid = reqData.SessionId;

            var BizUserDbItem = await DbUtils.DbHelper.GetOneAsync<Users>(p => p.EnterpriseId == enterId && p.BizUserId == jwtUser.BizUserID);
            if (BizUserDbItem == null || BizUserDbItem.KID == 0)
            {
                return new ResView() { code = 500, msg = "当前用户不存在，请核对后重试" };
            }
            var ImGroupDbItem = await DbUtils.DbHelper.GetOneAsync<ImGroups>(p => p.EnterpriseId == enterId && p.KID == groupId);
            if (ImGroupDbItem == null || ImGroupDbItem.KID == 0)
            {
                return new ResView() { code = 500, msg = "当前群里不存在，请核对后重试" };
            }
            #region 1 添加群-用户关联表数据
            var groupUserItems = new List<ImGroupUser>();
            foreach (var toUser in reqData.ToUser)
            {
                groupUserItems.Add(new ImGroupUser()
                {
                    KID = Builder.GetNewSnowId(),
                    EnterpriseId = reqview.AppId,
                    GroupId = groupId,
                    BizUserId = toUser.BizUserId,
                    JoinTime = DateTime.Now,
                    JoinState = 1,
                    JoinComment = "",
                    InviterBizUserId = reqData.BizUserId,
                    EnableTime = DateTime.Now.AddSeconds(-1)
                });
            }
            var addDb = await DbUtils.DbHelper.AddItemsAsync<ImGroupUser>(groupUserItems);
            if (addDb == 0)
            {
                return new ResView() { code = 500, msg = "邀请用户加入群聊失败，请稍后重试" };
            }
            #endregion

            #region 2 加一个会话  给 自己和 所有用户 都加上这个会话
            var sessionItems = new List<MySession>();
            foreach (var toUser in reqData.ToUser)
            {
                sessionItems.Add(new MySession()
                {
                    SessionId = sessionKid,
                    EnterpriseId = reqview.AppId,
                    BizUserId = toUser.BizUserId,
                    ToUserId = groupId.ToString(),
                    IsGroup = 1,
                    FullName = toUser.FullName,
                    HeadImg = toUser.HeadImg
                });
            }

            addDb = await DbUtils.DbHelper.AddItemsAsync<MySession>(sessionItems);
            if (addDb == 0)
            {
                return new ResView() { code = 500, msg = "群聊会话创建失败，请稍后重试" };
            }
            #endregion

            #region 3 给被邀用户 发送 type=1的新会话消息
            var sessionmsg = new Msg_Session
            {
                type = 1,
                sessionid = sessionKid,
                session = new SessionItem()
                {
                    isgroup = 1,
                    toUserId = groupId.ToString(),
                    fullname = ImGroupDbItem.FullName,
                    headimg = ImGroupDbItem.HeadImg,
                    flags = ImGroupDbItem.Flags
                }
            };
            await ImMsgLogic.SendSessionMsg(sessionmsg, reqData.ToUser.Select(p => p.BizUserId), BizUserDbItem.KID);

            #endregion

            #region 4.给当前群里 在线的用户 发送 type=0 第二层stype=1的消息 =>新用户入群消息
            //直接给用户发消息 就 ok 了
            var allImGroupUsers = await DbUtils.DbHelper.GetListAsync<ImGroupUser>(p => p.GroupId == groupId);

            var addUserNames = reqData.ToUser.Select(p => p.FullName).ToList();
            var msgChat = new Msg_Chat
            {
                type = 0,
                sessionid = reqview.Data.SessionId,
                send = new Chat_Send()
                {
                    stype = 1,
                    content = $"{BizUserDbItem.FullName}邀请了（{string.Join("、", addUserNames)}）加入群聊"
                }
            };
            await ImMsgLogic.SendChatMsg(reqview.AppId, msgChat, allImGroupUsers.Select(p => p.BizUserId), 0, BizUserDbItem);
            #endregion

            return new ResView() { code = 200, msg = "邀请成功" };
        }

        /// <summary>
        /// 主动退出一个群聊
        /// </summary>
        /// <param name="reqview"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResView> Quit([FromBody] ReqView<QuitGroupReq> reqview)
        {
            var jwtUser = GetUseByJwtToken();

            if (jwtUser.EnterpriseId != reqview.AppId.ToString())
            {
                return await ReturnFailed(302, "当前Token和登录用户信息不匹配，请核对修改后重试");
            }

            var enterId = reqview.AppId;
            var userBizId = jwtUser.BizUserID;
            var groupId = reqview.Data.GroupId.ToString();

            var BizUserDbItem = await DbUtils.DbHelper.GetOneAsync<Users>(p => p.EnterpriseId == enterId && p.BizUserId == jwtUser.BizUserID);
            if (BizUserDbItem == null || BizUserDbItem.KID == 0)
            {
                return new ResView() { code = 500, msg = "当前用户不存在，请核对后重试" };
            }


            #region 1 删群用户
            var delDb = await DbUtils.DbHelper.DeleteItemAsync<ImGroupUser>(p => p.EnterpriseId == enterId && p.BizUserId == userBizId);
            if (delDb == 0)
            {
                return new ResView() { code = 500, msg = "主动退出群聊失败,请稍后再试" };
            }
            #endregion

            #region 2 给群里其他用户 发消息 需要先发消息 后删除
            //获取当前群里面的所有用户
            var allImGroupUsers = (await DbUtils.DbHelper.LeftJoinAsync<Users, ImGroupUser, Users>((a, b) => a.BizUserId == b.BizUserId && a.EnterpriseId == b.EnterpriseId, (a, b) => b.GroupId == reqview.Data.GroupId)).Select(p => p.BizUserId);

            var chatmsg = new Msg_Chat
            {
                type = 0,
                sessionid = reqview.Data.SessionId,
                send = new Chat_Send()
                {
                    stype = 1,
                    content = $"\"{BizUserDbItem.FullName}\" 退出后了群聊"
                }
            };

            await ImMsgLogic.SendChatMsg(reqview.AppId, chatmsg, allImGroupUsers, 0, BizUserDbItem);

            #endregion

            #region 3 删除自己的群对应的会话
            delDb = await DbUtils.DbHelper.DeleteItemAsync<MySession>(p => p.SessionId == reqview.Data.SessionId && p.BizUserId == jwtUser.BizUserID);
            if (delDb == 0)
            {
                return new ResView() { code = 500, msg = "删除我的会话失败,请稍后再试" };
            }
            #endregion

            return new ResView() { code = 200, msg = "操作成功" };

        }

        /// <summary>
        /// 从群里 移除一些人
        /// </summary>
        /// <param name="reqview"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResView> RemoveUser([FromBody] ReqView<JoinGroupReq> reqview)
        {
            var jwtUser = GetUseByJwtToken();

            if (jwtUser.EnterpriseId != reqview.AppId.ToString())
            {
                return await ReturnFailed(302, "当前Token和登录用户信息不匹配，请核对修改后重试");
            }

            if (jwtUser.BizUserID != reqview.Data.BizUserId)
            {
                return await ReturnFailed(302, "当前Token和业务BizUserId信息不匹配，请核对修改后重试");
            }

            if (reqview.Data?.ToUser?.Count() == 0)
            {
                return new ResView() { code = 500, msg = "移除用户为空" };
            }

            /*
             *  1.删除群用户 保留会话,可以查历史消息		
		        2.给现有用户发消息
		        3.被移除的人发消息
             */
            var delUserIds = reqview.Data.ToUser.Select(p => p.BizUserId).ToList();
            var delImGroupUser = await DbUtils.DbHelper.DeleteItemAsync<ImGroupUser>(p => p.GroupId == reqview.Data.GroupId && delUserIds.Contains(p.BizUserId));

            if (delImGroupUser == 0)
            {
                return new ResView() { code = 500, msg = "删除群用户失败，请稍后再试" };
            }

            var allImGroupUser = await DbUtils.DbHelper.GetListAsync<ImGroupUser>(p => p.GroupId == reqview.Data.GroupId);
            var removeUserName = string.Join(",", reqview.Data.ToUser.Select(p => p.FullName));
            var chatmsg = new Msg_Chat()
            {
                type = 0,
                sessionid = reqview.Data.SessionId,
                send = new Chat_Send()
                {
                    stype = 0,
                    content = $"\"{removeUserName}\"已被\"{jwtUser.UserName}\"移除群聊"
                }
            };
            await ImMsgLogic.SendChatMsg(reqview.AppId, chatmsg, allImGroupUser.Select(p => p.BizUserId), Convert.ToInt64(jwtUser.UserKid));

            return new ResView() { code = 200, msg = "移除成功" };
        }


        /// <summary>
        /// 修改名称 可以单独修改
        /// 修改的json data里面的key对应字段 支持 GroupId FullName Comment HeadImg ExJson flags 其余字段不允许修改
        /// 且 字典里面 必须包含 GroupId 作为更新条件
        /// </summary>
        /// <param name="reqview"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResView> UpName([FromBody] ReqView<Dictionary<string, object>> reqview)
        {
            var cannUpKeys = "groupid,fullname,comment,headimg,exjson,flags".Split(',');

            var kid = "";

            var upDic = new Dictionary<string, object>();
            foreach (var item in reqview.Data)
            {
                if (item.Key.ToLower() == "groupid")
                {
                    kid = item.Value.ToString();
                    continue;
                }
                if (cannUpKeys.Contains(item.Key.ToLower()) && !item.Value.IsNull())
                {
                    upDic[item.Key] = item.Value.ToString();
                }
            }
            if (string.IsNullOrWhiteSpace(kid) || upDic.Count() == 0)
            {
                return new ResView() { code = 500, msg = "条件必须包含 GroupId 和 需修改的信息值" };
            }
            upDic[nameof(ImGroups.KID)] = Convert.ToInt64(kid);

            var upDb = await DbUtils.DbHelper.UpdateByDicAsync<ImGroups>(upDic, nameof(ImGroups.KID));
            return new ResView()
            {
                code = upDb > 0 ? 200 : 500,
                msg = upDb > 0 ? "更新成功" : "更新失败"
            };
        }
    }
}
